//
//  UAOracleConnection.m
//  Unidbaccess
//
//  Created by Toplica Tanasković on 12/13/08.
//  Copyright 2008 HOME. All rights reserved.
//

#import "UAOracleConnection.h"
#import "UAOracleStatement.h"
#include <ocilib.h>

@implementation UAOracleConnection

static BOOL ocilibInitialized = NO;

static UAError * globalError = nil;

static void err_handler(OCI_Error * error) {
	NSLog(@"Error handler is called!");
	OCI_Connection *		connection = OCI_ErrorGetConnection(error);
	UAOracleConnection *	oracleConnection = OCI_GetUserData(connection);
	NSNumber *				errorCode = [NSNumber numberWithInt: OCI_ErrorGetOCICode(error)];
	NSString *				errorMessage = [NSString stringWithUTF8String: OCI_ErrorGetString(error)];
	NSDictionary *			errorInfo = [NSDictionary dictionaryWithObjectsAndKeys: 
										 errorCode, @"errorCode", errorMessage, @"errorMessage", nil];
	UAError *				oracleError = [[UAError alloc] initWithErrorInfo: errorInfo];

	if (oracleConnection != nil) {
		[oracleConnection setLastError: oracleError];
	} else {
		NSLog(@"Using global error!");
		if (globalError != nil) {
			[globalError release];
		}
		globalError = [[UAError alloc] initWithErrorInfo: errorInfo];
	}
	[oracleError release];
	NSLog(@"Error code: %@ message: %@", errorCode, errorMessage);
}

- (id) initWithProperties: (NSDictionary *) aConnectionProperties {
	self = [super initWithProperties: aConnectionProperties];
	if (self) {
		if (!ocilibInitialized) {
			NSString *		oraHome = [connectionProperties valueForKey: @"oracleHome"];
			const char *	oracleHome = NULL;
			if (oraHome != nil) {
				oracleHome = [oraHome UTF8String];
			}
			if (OCI_Initialize(err_handler, oracleHome, OCI_ENV_DEFAULT)) {
				ocilibInitialized = YES;
			} else {
				NSLog(@"OCILIB initialization has failed!");
				[self release];
				return nil;
			}
		}
	}
	
	return self;
}

- (void) dealloc {
	[super dealloc];
}

- (BOOL) connect {
	NSString * database = [connectionProperties valueForKey: @"database"];
	NSString * username = [connectionProperties valueForKey: @"username"];
	NSString * password = [connectionProperties valueForKey: @"password"];
	NSNumber * mode = [connectionProperties valueForKey: @"mode"];
	
	nativeConnection = OCI_ConnectionCreate([database UTF8String], [username UTF8String], [password UTF8String], [mode unsignedIntValue]);
	
	if (nativeConnection == NULL) {
		[self setLastError: globalError];
		connected = NO;
		return NO;
	}
	OCI_SetUserData(nativeConnection, self);
	connected = YES;
	return YES;
}

- (void) disconnect {
	if (connected) {
		OCI_ConnectionFree(nativeConnection);
		connected = NO;
	}
}

- (UAStatement *) prepareStatement: (NSString *) aQueryString {
	if (!connected) {
		[NSException raise: @"NotConnectedException" format: @"Before preparing any statement, connection to database must be established."];
	}
	
	OCI_Statement * ocilibStatement = OCI_StatementCreate(nativeConnection);
	if (!OCI_Prepare(ocilibStatement, [aQueryString UTF8String])) {
		OCI_StatementFree(ocilibStatement);
		return nil;
	}
	
	UAOracleStatement * oracleStatement = [[UAOracleStatement alloc] initWithStatementData: ocilibStatement];
	return oracleStatement;
}
@end
